/******************************************************************************
	Cobalt - utility libraries for building XNA games
	Copyright (C) 2008 Philip Djonov

	This program is free software; you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2 of the License, or (at your option)
	any later version.

	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
	for more details.

	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the
	
		Free Software Foundation, Inc.
		51 Franklin Street, Fifth Floor
		Boston, MA  02110-1301, USA.
******************************************************************************/

using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework.Graphics;

namespace Cobalt
{

	internal static class Helpers
	{

		public static void DisposeAndNull<T>( ref T obj )
		{
			try
			{
				IDisposable disp = obj as IDisposable;
				if( disp != null )
					disp.Dispose();
			}
			finally
			{
				obj = default( T );
			}
		}

		internal static unsafe void MemCpyF( void* dst, void* src, int numFloats )
		{
			float* d = (float*)dst;
			float* s = (float*)src;

			while( numFloats-- != 0 )
				*d++ = *s++;
		}

		public static float Clamp( float val, float min, float max )
		{
			if( val < min ) return min;
			if( val > max ) return max;
			return val;
		}

		public static int Clamp( int val, int min, int max )
		{
			if( val < min ) return min;
			if( val > max ) return max;
			return val;
		}

		public static float Saturate( float val )
		{
			return Clamp( val, 0, 1 );
		}

		public static void EnsureArray<T>( ref T[] array, int count )
		{
			if( array == null )
				array = new T[count];
			else if( array.Length < count )
				Array.Resize( ref array, count );
		}

		public static int ElemsToPrims( PrimitiveType primType, int elemCount )
		{
			if( elemCount < 0 )
				throw new ArgumentOutOfRangeException( "elemCount" );

			switch( primType )
			{
			case PrimitiveType.PointList:
				return elemCount;

			case PrimitiveType.LineList:
				return elemCount / 2;

			case PrimitiveType.LineStrip:
				return elemCount >= 2 ? elemCount - 1 : 0;

			case PrimitiveType.TriangleList:
				return elemCount / 3;

			case PrimitiveType.TriangleStrip:
			case PrimitiveType.TriangleFan:
				return elemCount >= 3 ? elemCount - 2 : 0;

			default:
				throw new ArgumentException();
			}
		}

		public static int PrimsToElems( PrimitiveType primType, int primCount )
		{
			if( primCount < 0 )
				throw new ArgumentOutOfRangeException( "primCount" );

			switch( primType )
			{
			case PrimitiveType.PointList:
				return primCount;

			case PrimitiveType.LineList:
				return primCount * 2;

			case PrimitiveType.LineStrip:
				return primCount > 0 ? primCount + 1 : 0;

			case PrimitiveType.TriangleList:
				return primCount * 3;

			case PrimitiveType.TriangleStrip:
			case PrimitiveType.TriangleFan:
				return primCount > 0 ? primCount + 2 : 0;

			default:
				throw new ArgumentException();
			}
		}

		public static unsafe int ParseHex( char* s, int count )
		{
			int ret = 0;

			while( count-- != 0 )
			{
				int c = *s++;

				ret <<= 4;

				if( c >= '0' && c <= '9' )
					ret += c - '0';
				else if( c >= 'a' && c <= 'f' )
					ret += c - 'a' + 10;
				else if( c >= 'A' && c <= 'F' )
					ret += c - 'A' + 10;
				else
					return -1;
			}

			return ret;
		}
	}

}